博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django 图片上传upload_to路径指定失效的问题记录
阅读量:6502 次
发布时间:2019-06-24

本文共 6835 字,大约阅读时间需要 22 分钟。

  hot3.png

初始方法一:

疑虑:model使用upload_to自定义路径方法失效,指定路径也失效。最后以Views中指定MEDIA_URL和MEDIA_ROOT做拼接,并且自行判断并建立文件夹,手动chunk保存。不完美的解决。

model:    看avatar字段的upload_to

import uuidfrom django.db import modelsfrom django.contrib.auth.models import AbstractUserclass SysUser(AbstractUser):    """    用户扩展表,用于替换auth的user类,并添加头像和昵称。    """    uid = models.BigAutoField(primary_key=True)    nickname = models.CharField(max_length=32, verbose_name="昵称")    # 使用 models.ImageField 需要安装 Pillow ,cmd命令:pip install Pillow    avatar = models.ImageField(verbose_name="头像", upload_to="avatar11")    class Meta:        # 数据库显示的表名        db_table = "sys_user"

form:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsclass EditUserForm(Form):    """..."""    e_avatar = fields.ImageField(        required=False,        widget=widgets.FileInput(attrs={"hidden": "hidden"})    )    """..."""

Views:

def upload_user_avatar(request):    """用户上传头像操作"""    if request.method == "POST":        user_id = request.user.uid        # 只是当前登录用户        ret = {'state': True, 'error': None, 'data': None}        # user_id = request.POST.get("uid", None)        avatar = request.FILES.get("avatar", None)        # 如果文件夹不存在,则建立        dir_path = os.path.join(MEDIA_ROOT, "users", "{}_{}".format(request.user.uid, request.user.username), "avatar")        if not os.path.exists(os.path.join(dir_path)):            os.makedirs(os.path.join(dir_path))        avatar_path = os.path.join(dir_path, avatar.name)        try:            with open(avatar_path, 'wb+') as img:                for chunk in avatar.chunks():                    img.write(chunk)                print("文件接收成功")            img_url = os.path.join("users", "{}_{}".format(request.user.uid, request.user.username), "avatar")            SysUser.objects.filter(uid=user_id).update(avatar=img_url)            ret["data"] = "头像更新成功"        except Exception as e:            ret["state"] = False            ret["data"] = "头像更新失败,请确认图片格式"            print(e)        return HttpResponse(json.dumps(ret))

html:

 

  • SysUser.objects.filter(uid=user_id).update(avatar=img_url)
  • 这句话执行结束后,只保存文件名,无法使用upload_to指定的路径。
  • 页面加载时,直接使用拼接后路径。

初始方法二:

TMD,一个保存方式的问题,竟然能啰啰嗦嗦这么久。以后以此方法操作。

model:不变

views:

def upload_user_avatar(request):    """用户上传头像操作"""    if request.method == "POST":        user_id = request.user.uid        # 只是当前登录用户        ret = {'state': True, 'error': None, 'data': None}        avatar = request.FILES.get("avatar", None)        try:            user_obj = SysUser.objects.filter(uid=user_id).first()            user_obj.avatar = avatar            user_obj.save()            ret["data"] = "头像更新成功"        except Exception as e:            ret["state"] = False            ret["data"] = "头像更新失败,请确认图片格式"            print(e)        return HttpResponse(json.dumps(ret))
  • user_obj.save()
  • 使用这种保存方式的好处:
  1. 会自动保存文件路径到数据库
  2. 会自动保存文件到指定路径
  3. 必要时会自动创建目录。

目前最终方法:

model:

import uuidimport osfrom django.db import modelsfrom django.contrib.auth.models import AbstractUser"""python-cmd : makemigrationspython-cmd : migrate"""def user_directory_path(instance, filename):    """用户上传文件时的自定义操作"""    ext = filename.split('.')[-1]                           # 获取上传的文件名的后缀    filename = '{0}.{1}'.format(uuid.uuid4().hex[:8], ext)  # 修改文件名,谨防重名。(文档说重名后,会自动增加后缀)    sub_folder = 'avatar'    # 日后如果对上传文件的类型进行归档时可以COPY这个做参考。    # if ext.lower() in ["jpg", "png", "gif", "ico"]:    #    sub_folder = "avatar"    # if ext.lower() in ["pdf", "docx"]:    #     sub_folder = "document"    return os.path.join("users", "%s-%s" % (instance.user.uid, instance.user.username), sub_folder, filename)class SysUser(AbstractUser):    """    用户扩展表,用于替换auth的user类,并添加头像和昵称。    """    uid = models.BigAutoField(primary_key=True)    nickname = models.CharField(max_length=32, verbose_name="昵称")    # 使用 models.ImageField 需要安装 Pillow ,cmd命令:pip install Pillow    avatar = models.ImageField(verbose_name="头像", upload_to=user_directory_path)    class Meta:        # 数据库显示的表名        db_table = "sys_user"

form:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsclass EditUserForm(Form):    """..."""    e_avatar = fields.ImageField(        required=False,        widget=widgets.FileInput(attrs={"hidden": "hidden"})    )    """页面操作该元素时,使用的ajax方式,所以仅对此项进行操作。未使用EditUserForm做验证等操作。"""    """..."""

views:

def upload_user_avatar(request):    """用户上传头像操作"""    if request.method == "POST":        user_id = request.user.uid        # 只是当前登录用户        ret = {'state': True, 'error': None, 'data': None}        # user_id = request.POST.get("uid", None)   # 如果以后有需求修改其他人的信息时,再从页面获取。        avatar = request.FILES.get("avatar", None)        try:            user_obj = SysUser.objects.filter(uid=user_id).first()            user_obj.avatar = avatar            user_obj.save()            ret["data"] = "头像更新成功"        except Exception as e:            ret["state"] = False            ret["data"] = "头像更新失败,请确认图片格式"            print(e)        return HttpResponse(json.dumps(ret))

html:

JS:

// 上传文件按钮(label里的图片)点击事件$('#id_e_avatar').on('change',function () {	// 文件上传之前在本地加载预览。	{		// 获取用户最后一次选择的图片		var choose_file=$(this)[0].files[0];		// 创建一个新的FileReader对象,用来读取文件信息		var reader=new FileReader();		// 读取用户上传的图片的路径		reader.readAsDataURL(choose_file);		// 读取完毕之后,将图片的src属性修改成用户上传的图片的本地路径		reader.onload=function () {			 $("#avatar-img").attr("src",reader.result)		}	}	// 使用FormData格式,将文件上传至服务器	formdata = new FormData();	//formdata.append('uid',$('#id_e_id').val());	formdata.append("avatar",$("#id_e_avatar")[0].files[0]);	$.ajax({		type: "POST",		url: "/account/upload_user_avatar",		data:formdata,		processData:false,	//上传文件时需要如此设置1		contentType:false,	//上传文件时需要如此设置2		success:function (data) {			data = JSON.parse(data);			console.log(data);			alert(data.data)	// 偷懒了,哈哈         }	});});

media_url映射:

from django.urls import path, re_path, includefrom django.views.generic.base import RedirectViewfrom django.views.static import serve    # 映射media_root路径,可以通过浏览器访问的操作-1from django.contrib.auth.decorators import login_requiredfrom WXH_DJANGOWEB import settingsfrom utils.required import requiredurlpatterns = [    path('account/', include("account.urls")),    path('blog/', include("blog.urls")),    re_path(r"^media/(?P
.*)$", serve, {"document_root": settings.MEDIA_ROOT, }) # 映射media_url,可以通过浏览器访问的操作-2]

至此,记录完毕。回家吃饭。坑爹的保存方式…… 愿同志们绕坑而行,用不遇坑。

转载于:https://my.oschina.net/asktao/blog/3004672

你可能感兴趣的文章
JDBC_MySQL_jdbc连接mysql_MySQL
查看>>
mysql cte的好处_Mysql 8 重要新特性 - CTE 通用表表达式
查看>>
zcu106 固化_xilinx zcu106 vcu demo
查看>>
java ftpclient 代码_java后台代码ftpclient下载文件
查看>>
java数据库生成model_继承BaseModelGenerator 生成Model时添加数据库表字段 生成代码示例...
查看>>
matlab建立桌面图标,在ubuntu16.04上创建matlab的快捷方式(实现方法)
查看>>
smarty使用php代码,笑谈配置,使用Smarty技术_php
查看>>
oracle数据实际值限制,c# – Oracle数据库TNS密钥“数据源”的值长度超过了’128’的限制...
查看>>
silk v3 decoder php,解码转换QQ微信的SILK v3编码音频为MP3或其他格式
查看>>
linux不能访问80端口,lunux开放80端口(本地访问不了linux文件可能是这个原因)...
查看>>
android单位转换小程序,微信小程序中rpx与rem单位转换
查看>>
ps切图教程 android,PS前端切图完整教程
查看>>
HTML如何把输入框变成必填值,required输入框为必填项
查看>>
背锅侠逆袭之路
查看>>
演示:使用协议分析器取证IPv6的报文结构
查看>>
oracle 11gr2 rac中的4种IP解说
查看>>
为什么你找不到工作?
查看>>
汇编语言的应用
查看>>
device platform 相应的表
查看>>
php des 加密解密实例
查看>>